package main

import (
	"bufio"
	"context"
	"flag"
	"fmt"
	"io"
	"os"
	"reverse_read"
	"runtime"
	"strconv"
	"strings"
	"time"
	"unsafe"
	// "github.com/axgle/mahonia"
)

// 实例化全局对象
var (
	pis_data   *Parameter_is  = &Parameter_is{}
	ois_data   *Parameter_ois = &Parameter_ois{}
	pss_data   *Parameter_ss  = &Parameter_ss{}
	pzz_data   *Parameter_zz  = &Parameter_zz{}
	all_store  mapstore       = mapstore{}
	read_store                = make(chan *string)
	one_store                 = make(chan *string)
	two_store                 = make(chan *string)

	file_path       string = ""
	write_file_path string = ""
	continue_print  bool   = false
	r_read_way      bool   = false

	system_enter string = "\r\n"
)

// 初始化绑定flag
func init() {
	flag.Var(&pis_data.in_related_string, "a", "根据指定字符查询(符合所有条件), 通过|分隔")
	flag.Var(&pis_data.out_related_string, "p", "排除指定字符查询, 通过|分隔")
	flag.Var(&pis_data.or_related_string, "m", "根据指定字符查询(符合单个条件), 通过|分隔")
	flag.StringVar(&pis_data.updown_type, "S", "default", "范围打印模式, 仅支持字符查询匹配, 不进行范围打印: default; 向上范围打印: up;向下范围打印: down;统一打印: all")
	flag.IntVar(&pis_data.upward_num, "su", 0, "向上匹配打印的范围（包含匹配的行）")
	flag.IntVar(&pis_data.down_num, "sd", 0, "向下匹配打印的范围")
	flag.StringVar(&ois_data.one_in_string, "o", "none", "匹配指定字符（单个）的出现总次数")
	flag.StringVar(&pss_data.split_symbol, "s", "none", "分隔符")
	flag.StringVar(&pss_data.split_type, "M", "none", "截取模式：jane 简单, num, sum, avg")
	flag.Var(&pss_data.split_location, "l", "填写指定的位置, 简单模式可指定多个, 通过|分隔, 如0|5|$, 按顺序写入, 其他模式仅允许单个")
	flag.StringVar(&pzz_data.regular_grammar, "r", "none", "正则匹配规则(golang语法)")
	flag.StringVar(&pzz_data.regular_type, "t", "match", "正则匹配类型, filter: 打印匹配到的数据; match: 打印匹配到数据的行")
	flag.StringVar(&file_path, "f", "", "文件路径")
	flag.StringVar(&write_file_path, "w", "", "打印文件的路径")
	flag.BoolVar(&continue_print, "c", false, "是否持续打印, 默认为false")
	flag.BoolVar(&r_read_way, "the", false, "是否反向打印, 默认为false")

	if runtime.GOOS != "windows" {
		system_enter = "\n"
	}
}

func Init_start(smanage *State_manage) {
	var true_sum int // 二级匹配判断的依据
	pis_data_status, err := pis_data.Init_judge()
	if err != nil {
		smanage.error_status = 1
		smanage.error_txt = err
		smanage.cancel()
		return
	}
	if pis_data_status {
		all_store["pis_data_store"] = bytestore{
			storetype:   "pis_data_store",
			status:      pis_data_status,
			object:      pis_data,
			read_status: true,
		}
	}

	ois_data_status, _ := ois_data.Init_judge()
	if ois_data_status {
		all_store["ois_data_store"] = bytestore{
			storetype:   "ois_data_store",
			status:      all_store["pis_data_store"].status,
			read_status: !all_store["pis_data_store"].status,
			object:      ois_data,
		}
		true_sum += 1
	}
	pss_data_status, err := pss_data.Init_judge()
	if err != nil {
		smanage.error_status = 1
		smanage.error_txt = err
		smanage.cancel()
		return
	} else {
		if pss_data_status {
			all_store["pss_data_store"] = bytestore{
				storetype:   "pss_data_store",
				status:      all_store["pis_data_store"].status,
				read_status: !all_store["pis_data_store"].status,
				object:      pss_data,
			}
			true_sum += 1
		}
	}
	pzz_data_status, err := pzz_data.Init_judge()
	if err != nil {
		smanage.error_status = 1
		smanage.error_txt = err
		smanage.cancel()
		return
	} else {
		if pzz_data_status {
			all_store["pzz_data_store"] = bytestore{
				storetype:   "pzz_data_store",
				status:      all_store["pis_data_store"].status,
				read_status: !all_store["pis_data_store"].status,
				object:      pzz_data,
			}
			true_sum += 1
		}
	}
	if true_sum > 1 {
		smanage.error_status = 1
		smanage.error_txt = fmt.Errorf("功能型查询不允许重复")
		smanage.cancel()
		return
	}
	if true_sum >= 1 && pis_data.updown_type != "default" {
		smanage.error_status = 1
		smanage.error_txt = fmt.Errorf("范围打印仅允许普通匹配-a或-m")
		smanage.cancel()
		return
	}
	if ois_data_status || pss_data_status || pis_data_status || pzz_data_status {
		all_store.mapstart()
	} else {
		smanage.error_status = 1
		smanage.error_txt = fmt.Errorf("必须填写参数")
		smanage.cancel()
		return
	}
}

func Run() {
	ctx, cancel := context.WithCancel(context.Background())
	smanage := &State_manage{
		ctx:          ctx,
		cancel:       cancel,
		error_status: 0,
	}

	if file_path == "" {
		smanage.error_status = 1
		smanage.error_txt = fmt.Errorf("必须设置文件路径")
		smanage.cancel()
	} else {
		Init_start(smanage)
		if r_read_way {
			go Readr(file_path, smanage)
		} else {
			go Reado(file_path, smanage)
		}
	}
	if all_store.Len() > 1 {
		if smanage.error_status == 0 && write_file_path != "" {
			authority, err := os.Create(write_file_path)
			defer authority.Close()
			if err != nil {
				smanage.error_status = 1
				smanage.error_txt = fmt.Errorf("文件创建异常")
				smanage.cancel()
				Printo(smanage, one_store)
			} else {
				Writeo(authority, two_store)
			}
		} else {
			Printo(smanage, two_store)
		}

	} else {
		if smanage.error_status == 0 && write_file_path != "" {
			authority, err := os.Create(write_file_path)
			defer authority.Close()
			if err != nil {
				smanage.error_status = 1
				smanage.error_txt = fmt.Errorf("文件创建异常")
				smanage.cancel()
				Printo(smanage, one_store)
			} else {
				Writeo(authority, one_store)
			}
		} else {
			Printo(smanage, one_store)
		}
	}
}

func close_channel() {
	close(read_store)
	close(one_store)
	close(two_store)
}

func Reado(path string, status *State_manage) {
	f, err := os.Open(path)
	if err != nil {
		status.error_status = 1
		status.error_txt = fmt.Errorf("文件读取失败")
		status.cancel()
		return
	}
	defer func() {
		f.Close()
		close(read_store)
	}()
	// 对ANSI编码转换
	// decoder := mahonia.NewDecoder("gbk")
	// r := bufio.NewReader(decoder.NewReader(f))
	r := bufio.NewReader(f)

	for {
		d, err := r.ReadBytes('\n')
		if err == io.EOF {
			if continue_print { // 支持持续打印
				time.Sleep(time.Millisecond * 500)
				continue
			} else {
				fmt.Println("文件读取完成")
				return
			}

		}
		if err != nil {
			status.error_status = 1
			status.error_txt = fmt.Errorf("文件读取异常")
			status.cancel()
			return
		}
		select {
		case <-status.ctx.Done():
			return
		default:
			s := string(d)
			read_store <- &s
		}
	}
}

func Readr(path string, status *State_manage) {
	r, err := reverse_read.NewReadLineFromEnd(path)
	if err != nil {
		status.error_status = 1
		status.error_txt = fmt.Errorf("文件读取失败")
		status.cancel()
		return
	}
	defer func() {
		r.Close()
		close(read_store)
	}()
	for {
		d, err := r.ReadLine()
		if err == io.EOF {
			if continue_print { // 支持持续打印
				time.Sleep(time.Millisecond * 500)
				continue
			} else {
				fmt.Println("文件读取完成")
				return
			}

		}
		if err != nil {
			status.error_status = 1
			status.error_txt = fmt.Errorf("文件读取异常")
			status.cancel()
			return
		}
		select {
		case <-status.ctx.Done():
			return
		default:
			s := string(d)
			read_store <- &s
		}
	}
}

func Writeo(write_file *os.File, pchannel chan *string) {
	for {
		pdata, isclosed := <-pchannel
		if !isclosed { // 输出层写完后就close掉
			return
		}
		fmt.Print(*pdata)
		write_file.WriteString(*pdata)
	}
}

func Printo(status *State_manage, pchannel chan *string) {
	if status.error_status != 0 {
		fmt.Println("异常: ", status.error_txt)
		return
	}
	for {
		pdata, isclosed := <-pchannel
		if !isclosed { // 输出层写完后就close掉
			if status.error_status != 0 {
				fmt.Println("异常: ", status.error_txt)
			}
			return
		}
		fmt.Print(*pdata)
	}
}

// 方法
// 字符切割
func Avg_strtoint(sary []string) ([]int64, error) {
	var iary []int64
	for _, d := range sary {
		if d == "$" {
			iary = append(iary, -1)
			break
		}
		i, err := strconv.ParseInt(d, 0, 64)
		if err != nil {
			return nil, fmt.Errorf("%s is not int", d)
		}
		iary = append(iary, i)
	}
	return iary, nil
}

// 字符二进制转换(有乱码问题)
func strTobytes(s *string) []byte {
	x := (*[2]uintptr)(unsafe.Pointer(s))
	h := [3]uintptr{x[0], x[1], x[1]}
	return *(*[]byte)(unsafe.Pointer(&h))
}

func bytesTostr(b *[]byte) *string {
	return (*string)(unsafe.Pointer(b))
}

// 字符匹配
func symbol_judge(k string, v string) bool {
	if strings.HasPrefix(k, "^") {
		return strings.HasPrefix(v, k[1:])
	}
	if strings.HasSuffix(k, "$") {
		return strings.HasSuffix(v, k[:len(k)-1])
	}
	return strings.Contains(v, k)
}

//符号处理
func txt_mod(k string) string {
	if strings.HasPrefix(k, "^") {
		return k[1:]
	}
	if strings.HasSuffix(k, "$") {
		return k[:len(k)-1]
	}
	return k
}

//符号修改
func symbol_mod(s string) ([]string, error) {
	var f []string
	l := len(s)
	n := 0
	start := 0
	if strings.HasSuffix(s, ",") {
		return nil, fmt.Errorf("不能以逗号结尾") // 逗号结尾
	}
	for i := 0; i < l; i++ {
		if s[i:i+1] == "," {
			if i >= 1 {
				if s[i-1:i] != "," {
					f = append(f, s[start:i])
				}
			}
			start = i + 1
			n++
		}
	}
	f = append(f, s[start:])
	poor := n - len(f)
	if poor == 1 { // 有逗号为分隔符的情况
		f = append(f, ",")
	} else if poor == -1 {

	} else {
		return nil, fmt.Errorf("逗号之间需包含字符") // 重复逗号(连续逗号超过3个，或逗号开头连续超过2个)
	}
	return f, nil
}

// 字符串切割，返回切割后的数组
func split_judge(s []string, k []string, l int, return_list []string) []string {
	if l == len(k) {
		return nil
	}
	for _, ls := range s {
		sdata := strings.Split(ls, k[l])
		rls := split_judge(sdata, k, l+1, return_list)
		if rls != nil {
			return_list = append(return_list, rls...)
		} else {
			return_list = append(return_list, sdata...)
		}
	}
	return return_list
}

// 循环去除数组中的数据
func obtain_data(s []string, l []int64) (string, bool) {
	r := []string{}
	le := int64(len(s))
	for _, i := range l {
		if i >= le {
			return "", false
		}
		if i == -1 {
			r = append(r, s[le-1])
		} else {
			r = append(r, s[i])
		}

	}
	rs := strings.Join(r, " ")
	return rs, true
}

func main() {
	flag.Parse()
	Run()
}
